package io.rehuo.modules.app.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.rehuo.common.exception.RRException;
import io.rehuo.common.utils.DateUtils;
import io.rehuo.common.utils.RedisUtils;
import io.rehuo.common.utils.ServletUtils;
import io.rehuo.common.utils.pay.HQPayUtils;
import io.rehuo.common.utils.pay.VaUtils;
import io.rehuo.modules.app.dao.ApplyDao;
import io.rehuo.modules.app.entity.*;
import io.rehuo.modules.app.entity.vo.AccountEntity;
import io.rehuo.modules.app.entity.vo.ApplyVo;
import io.rehuo.modules.app.entity.vo.PaymentBankVo;
import io.rehuo.modules.app.enums.PayCompanyEnum;
import io.rehuo.modules.app.service.*;
import io.rehuo.modules.app.utils.StrUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

/**
 * @author shiguang
 * @date 2022年09月12日 11:26
 */
@Service("applyService")
public class ApplyServiceImpl extends ServiceImpl<ApplyDao, ApplyEntity> implements ApplyService {

    @Autowired
    private UserService userService;

    @Autowired
    private ConfigService configService;

    @Autowired
    private UserCompanyService userCompanyService;

    @Autowired
    private RepaymentLogService repaymentLogService;

    @Autowired
    private CompanyService companyService;

    @Autowired
    private UserVaService userVaService;

    @Autowired
    private PayConfigService payConfigService;

    @Autowired
    private BankService bankService;

    @Autowired
    private PayBankService payBankService;

    @Autowired
    private RedisUtils redisUtils;

    @Autowired
    private UserBankService userBankService;

    /**
     * 创建贷款信息
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveApply(UserEntity userEntity) {
        //判断用户状态
        checkUserStatus(userEntity);
        //判断用户是否有再借贷款
        checkUserApply(userEntity);
        //根据配置信息查询可贷款公司
        ConfigEntity configEntity = configService.selectOne();
        if (configEntity == null || StringUtils.isBlank(configEntity.getFirstApplyCompany())) {
            throw new RRException("Lỗi cấu hình hệ thống, xin vui lòng liên hệ với quản trị viên");
        }
        String[] strs = configEntity.getFirstApplyCompany().split(",");
        List<Long> ids = new ArrayList<>(strs.length);
        for (String str : strs) {
            ids.add(Long.valueOf(str));
        }
        //判断是轮询还是随机
        if (configEntity.getFirstApplyType().equals("0")) {
            //随机
            Long id = null;
            if (ids.size() > 1) {
                Random random = new Random();
                id = ids.get(random.nextInt(ids.size()));
            } else {
                id = ids.get(0);
            }
            //判断是否被冻结
            boolean flag = isFrozen(userEntity.getUserId(), id);
            if (flag) {
                //创建订单
                createApply(userEntity, id);
            } else {
                throw new RRException("Các khoản vay không thành công, tài khoản bị đóng băng");
            }
        } else if (configEntity.getFirstApplyType().equals("1")) {
            //轮询 查询上次首借公司
            ApplyEntity entity = baseMapper.selectOne(new QueryWrapper<ApplyEntity>().eq("first_apply", "0").orderByDesc().last("limit 1"));
            if (ObjectUtil.isNotNull(entity)) {
                int index = ids.indexOf(entity.getCompanyId());
                Long companyId = ids.get(index + 1);
                //判断是否被冻结
                boolean flag = isFrozen(userEntity.getUserId(), companyId);
                if (flag) {
                    //创建订单
                    createApply(userEntity, companyId);
                } else {
                    throw new RRException("Các khoản vay không thành công, tài khoản bị đóng băng");
                }
            } else {
                createApply(userEntity, ids.get(0));
            }
        } else if (configEntity.getFirstApplyType().equals("2")) {
            //所有
            for (Long companyId : ids) {
                //判断是否被冻结
                boolean flag = isFrozen(userEntity.getUserId(), companyId);
                if (flag) {
                    //创建订单
                    createApply(userEntity, companyId);
                }
            }
        }
//        userEntity.setStatus("4");
        userService.updateById(userEntity);
    }

    /**
     * 获取我的贷款列表
     *
     * @param type
     * @return
     */
    @Override
    public List<ApplyVo> getListByType(String type, UserEntity userEntity) {
        List<ApplyEntity> list = new ArrayList<>();
        List<ApplyVo> applyVoList = new ArrayList<>();
        if (type.equals("1")) {
            //获取待审核或待提现列表
            list = baseMapper.selectList(new QueryWrapper<ApplyEntity>()
                    .eq("user_id", userEntity.getUserId())
                    .in("status", "2", "1", "0", "3", "4", "5", "9", "10")
                    .orderByDesc("create_time")
            );
        } else if (type.equals("2")) {
            list = baseMapper.selectList(new QueryWrapper<ApplyEntity>()
                    .eq("user_id", userEntity.getUserId())
                    .in("status", "6", "8")
                    .orderByDesc("create_time")
            );
        }
        for (ApplyEntity entity : list) {
            //获取公司logo
            CompanyEntity companyEntity = companyService.selectById(entity.getCompanyId());
            applyVoList.add(createApplyVo(entity, companyEntity, null));
        }

        if (type.equals("3")) {
            List<RepaymentLogEntity> list1 = repaymentLogService.selectListByUserId(userEntity.getUserId());
            for (RepaymentLogEntity entity : list1) {
                //获取公司logo
                CompanyEntity companyEntity = companyService.selectById(entity.getCompanyId());
                applyVoList.add(createApplyVo(null, companyEntity, entity));
            }
        }

        return applyVoList;
    }

    @Override
    public ApplyEntity selectById(Long applyId) {
        ApplyEntity applyEntity = baseMapper.selectById(applyId);
        CompanyEntity companyEntity = companyService.selectById(applyEntity.getCompanyId());
        applyEntity.setCompanyEntity(companyEntity);
        return applyEntity;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void userWithdrawal(UserEntity userEntity, Long applyId) {
        ApplyEntity applyEntity = baseMapper.selectById(applyId);
        if (ObjectUtil.isNull(applyEntity)) {
            throw new RRException("apply order is null");
        }
        if (!applyEntity.getUserId().equals(userEntity.getUserId())) {
            throw new RRException("this apply order is error");
        }
        if (!applyEntity.getStatus().equals("4")) {
            throw new RRException("this apply order is error");
        }
        applyEntity.setStatus("5");
        applyEntity.setUpdateTime(new Date());
        applyEntity.setCashOutTime(new Date());
        UserBankEntity userBank = userBankService.getByUserId(userEntity.getUserId());
        applyEntity.setBankCardNo(userBank.getBankNo());
        applyEntity.setSimpleName(userBank.getSimpleName());
        baseMapper.updateById(applyEntity);
    }

    /**
     * 获取还款银行卡信息
     *
     * @param userEntity
     * @param applyId
     * @return
     */
    @Override
    public PaymentBankVo getPaymentBankInfo(UserEntity userEntity, Long applyId) {
        ApplyEntity applyEntity = baseMapper.selectById(applyId);
        if (ObjectUtil.isNull(applyEntity) || !applyEntity.getUserId().equals(userEntity.getUserId())) {
            throw new RRException("this apply order or user id is error");
        }
        PaymentBankVo paymentBankVo = null;
        //获取订单绑定的公司
        CompanyEntity companyEntity = companyService.selectById(applyEntity.getCompanyId());
        //判断是线下收款还是线上收款
        if (companyEntity.getPaymentType().equals("0") && companyEntity.getPaymentChannel() != null) {  //开启线上且有渠道的时候
            //查找订单对应支付渠道的虚拟卡
            UserVaEntity userVaEntity = userVaService.getOne(new QueryWrapper<UserVaEntity>().eq("apply_id", applyId).eq("pay_config_id", companyEntity.getPaymentChannel()));
            if (ObjectUtil.isNull(userVaEntity)) {
                //如果对应渠道没有虚拟卡  则查询订单是否有对应的虚拟卡
                userVaEntity = userVaService.getOne(new QueryWrapper<UserVaEntity>().eq("apply_id", applyId));
                if (ObjectUtil.isNull(userVaEntity)) {
                    //创建渠道对应的虚拟卡
                    PayConfigEntity payConfigEntity = payConfigService.getById(companyEntity.getPaymentChannel());
                    if (payConfigEntity.getPayCompany().equals(PayCompanyEnum.HQ_PAY.getCode())) {
                        //hqpay支付
                        String token = payConfigEntity.getHqpayToken();
                        if (StringUtils.isBlank(token)) {
//                            String loginResult = HQPayUtils.login(payConfigEntity.getMercharntId(), payConfigEntity.getAppId());
//                            JSONObject jsonObject = JSONObject.parseObject(loginResult);
//                            String tokenType = jsonObject.getJSONObject("data").getString("token_type");
//                            String accessToken = jsonObject.getJSONObject("data").getString("access_token");
//                            long expires = jsonObject.getJSONObject("data").getLongValue("expires_in");
//
//                            token = tokenType + " " + accessToken;
//                            redisUtils.set(Constants.HQ_PAY_TOKEN + payConfigEntity.getId(), token, expires);
                            throw new RRException("Khi xảy ra lỗi xin hãy liên hệ CSKH của chúng tôi");
                        }
                        //创建虚拟卡
                        if (payConfigEntity.getVaType().equals("1")) {
                            String cardResult = HQPayUtils.createVirtualCard(token);
                            JSONObject cardJsonResult = JSONObject.parseObject(cardResult);
                            if (cardJsonResult.getBoolean("success")) {
                                JSONObject data = cardJsonResult.getJSONObject("data");
                                UserVaEntity vaEntity = userVaService.saveUserVaHqpay(data, applyEntity, payConfigEntity);
                                paymentBankVo = new PaymentBankVo();
                                paymentBankVo.setBankCode(vaEntity.getAccountNo());
                                paymentBankVo.setAccountName(vaEntity.getAccountName());
                                BankEntity bankEntity = bankService.getOne(new QueryWrapper<BankEntity>().eq("hq_pay_bank_id", vaEntity.getBank()));
//                            paymentBankVo.setBankName(bankEntity.getBankName());
                                paymentBankVo.setBankName("Pvcombank");
                                return paymentBankVo;
                            }
                        }else{
                            try {
                                String cardResult = HQPayUtils.createNewVa(applyEntity.getOrderSn(), applyEntity.getUserName(),companyEntity.getName(), token);
                                JSONObject cardJsonResult = JSONObject.parseObject(cardResult);
                                if (cardJsonResult.getBoolean("ok")) {
                                    String batchId = cardJsonResult.getString("batch");
                                    JSONArray data = cardJsonResult.getJSONArray("accounts");
                                    String accounts = cardJsonResult.getString("accounts");
                                    List<AccountEntity> list = JSONObject.parseArray(accounts, AccountEntity.class);
                                    if (list.size() > 0) {
                                        userVaService.saveUserVaHqpayNew(list.get(0), applyEntity, payConfigEntity, batchId);
                                        paymentBankVo = new PaymentBankVo();
                                        paymentBankVo.setBankCode(list.get(0).getVaNumber());
                                        paymentBankVo.setAccountName(list.get(0).getVaName());
                                        paymentBankVo.setBankName("Pvcombank");
                                        return paymentBankVo;
                                    }
                                }
                            } catch (Exception e) {
                                log.error("创建虚拟账户异常:" + e.getMessage());
                            }
                        }
                    } else if (payConfigEntity.getPayCompany().equals(PayCompanyEnum.ODD_PAY.getCode())) {
                        Map<String, Object> map = VaUtils.createVa(payConfigEntity.getMercharntId(), payConfigEntity.getAppId(), applyEntity.getOrderSn(),
                                String.valueOf(applyEntity.getRealApplyMoney()), DateUtils.format(new Date(), "yyyyMMdd") + "000000",
                                DateUtils.format(DateUtils.addDateWeeks(new Date(), 2), "yyyyMMdd") + "235959",
                                userEntity.getUserName(), payConfigEntity.getVirtualNotifyUrl());
                        if (map != null && map.get("ret_code").equals("0000")) {
                            //创建虚拟卡
                            if (ObjectUtil.isNotNull(map.get("ret_data"))) {
                                UserVaEntity vaEntity = userVaService.saveUserVa(map.get("ret_data").toString(), applyEntity, payConfigEntity);
                                paymentBankVo = new PaymentBankVo();
                                paymentBankVo.setBankCode(vaEntity.getAccountNo());
//                                paymentBankVo.setBankName(vaEntity.getBank());
                                paymentBankVo.setAccountName(vaEntity.getAccountName());
//                                BankEntity bankEntity = bankService.getOne(new QueryWrapper<BankEntity>().eq("simple_name", vaEntity.getBank()));
                                paymentBankVo.setBankName(vaEntity.getBank());
                                return paymentBankVo;
                            }

                        }
                    }
                } else {
                    paymentBankVo = new PaymentBankVo();
                    paymentBankVo.setBankCode(userVaEntity.getAccountNo());
                    paymentBankVo.setAccountName(userVaEntity.getAccountName());
                    BankEntity bankEntity = bankService.getOne(new QueryWrapper<BankEntity>().eq("simple_name", userVaEntity.getBank()));
                    paymentBankVo.setBankName(bankEntity.getBankName());
                    return paymentBankVo;
                }
            } else {
                paymentBankVo = new PaymentBankVo();
                paymentBankVo.setBankCode(userVaEntity.getAccountNo());
                paymentBankVo.setAccountName(userVaEntity.getAccountName());
//                BankEntity bankEntity = bankService.getOne(new QueryWrapper<BankEntity>().eq("simple_name", userVaEntity.getBank()));
                if (StringUtils.isNumeric(userVaEntity.getBank())) {
                    paymentBankVo.setBankName("Pvcombank");
                } else {
                    paymentBankVo.setBankName(userVaEntity.getBank());
                }
                return paymentBankVo;
            }
        } else if (companyEntity.getPaymentType().equals("0") && companyEntity.getPaymentChannel() == null) {
            //开启线上且又没有渠道
            throw new RRException("pay bank is error");
        } else {
            //其余走线下
            //根据公司信息查询绑定的线下银行卡
            if (companyEntity.getPayBankId() != null) {
                PayBankEntity payBankEntity = payBankService.getById(companyEntity.getPayBankId());
                paymentBankVo = new PaymentBankVo();
                paymentBankVo.setBankCode(payBankEntity.getBankNo());
                paymentBankVo.setAccountName(payBankEntity.getBankUserName());
                paymentBankVo.setBankName(payBankEntity.getBankName());
                return paymentBankVo;
            }
        }
        return null;
    }

    private ApplyVo createApplyVo(ApplyEntity applyEntity, CompanyEntity companyEntity, RepaymentLogEntity repaymentLogEntity) {
        ApplyVo vo = new ApplyVo();
        if (applyEntity != null) {
            vo.setApplyId(applyEntity.getId());
            vo.setMoney(applyEntity.getRealApplyMoney() != 0 ? applyEntity.getRealApplyMoney() : (applyEntity.getApplyMoney() + applyEntity.getOverMoney()));
            vo.setDate(applyEntity.getRepaymentTime());
            vo.setStatus(applyEntity.getStatus());
            if (applyEntity.getApplyCycle() > 0) {
                vo.setApplyCycle(applyEntity.getApplyCycle());
            }
        }

        if (repaymentLogEntity != null) {
            vo.setApplyId(repaymentLogEntity.getApplyId());
            vo.setMoney(repaymentLogEntity.getRepaymentMoney());
            vo.setDate(DateUtils.format(repaymentLogEntity.getCreateTime()));
            vo.setStatus("2");
        }
        vo.setLogo(companyEntity.getLogo());
        vo.setCompanyName(companyEntity.getName());
        return vo;
    }

    private void checkUserApply(UserEntity userEntity) {
        Integer count = baseMapper.selectCount(new QueryWrapper<ApplyEntity>().eq("user_id", userEntity.getUserId()).eq("del_flag", "0").in("status", "0", "2", "4", "6", "8"));
        if (count > 0) {
            throw new RRException("Có dữ liệu cho vay");
        }
    }

    private void checkUserStatus(UserEntity userEntity) {
        if (userEntity == null) {
            throw new RRException("Người dùng không tồn tại");
        }
        if (!"3".equals(userEntity.getStatus())) {
            throw new RRException("Thông tin người dùng chưa được xác nhận");
        }
//        if (!"2".equals(userEntity.getOperatorStatus())) {
//            throw new RRException("运营商未认证");
//        }
    }

    /**
     * 创建订单
     *
     * @param userEntity 用户
     * @param companyId  公司id
     */
    public void createApply(UserEntity userEntity, Long companyId) {
        //判断该用户在改公司是否有正在贷款的记录
        Integer count = baseMapper.selectCount(new QueryWrapper<ApplyEntity>()
                .eq("company_id", companyId)
                .eq("user_id", userEntity.getUserId())
                .eq("del_flag", "0")
                .in("status", "7")
        );
        ApplyEntity applyEntity = new ApplyEntity();
        applyEntity.setUserName(userEntity.getUserName());
        applyEntity.setUserId(userEntity.getUserId());
        applyEntity.setCompanyId(companyId);

        applyEntity.setStatus("999");
        applyEntity.setApplyMoney(userEntity.getApplyMoney());
        applyEntity.setUserPhone(userEntity.getUserPhone());
        applyEntity.setOrderSn(StrUtils.getOrderNewNum(userEntity.getUserId()));
        applyEntity.setIdCardNumber(userEntity.getCardNo());
        applyEntity.setCreateTime(new Date());

        HttpServletRequest request = ServletUtils.getRequest();
        String ip = ServletUtils.getClientIP(request);
        applyEntity.setIpAddress(ip);
        applyEntity.setChannel(userEntity.getChannel());

        if (count == 0) {
            applyEntity.setFirstApply("0");
        } else {
            applyEntity.setFirstApply("2");
        }
        applyEntity.setApplyNum(count + 1);
        baseMapper.insert(applyEntity);
    }

    /**
     * 判断账户是否冻结
     *
     * @param userId
     * @param companyId
     * @return
     */
    private boolean isFrozen(Long userId, Long companyId) {
        UserCompanyEntity userCompanyEntity = userCompanyService.selectByUserIdAndCompanyId(userId, companyId);
        if (userCompanyEntity == null) {
            return true;
        } else {
            return false;
        }
    }

}
